package com.szp.spCloud.user.filter;

import com.alibaba.fastjson.JSON;
import com.szp.spCloud.common.pojo.R;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class IpFilter implements GlobalFilter, Ordered, InitializingBean {
    Logger logger = LoggerFactory.getLogger(IpFilter.class);
    //    config:
//  visit:
//    timeWindows: 10 #seconds
//    times: 10 # register times
    @Value("${config.visit.timeWindows}")
    private int timeWindow;

    @Value("${config.visit.times}")
    private int maxVisits;

    private Timer timer;

    private ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String uri = request.getURI().getPath();
        if (uri.indexOf("/api/user/register") == -1) {
            return chain.filter(exchange);
        }
        String sourceIp = request.getRemoteAddress().getHostString();
        Integer count = map.get(sourceIp);


        if (null == count) {
            logger.info("{}进行用户注册,最近{}秒时间内访问次数为{}", sourceIp, timeWindow, 1);
            map.put(sourceIp, 1);
            return chain.filter(exchange);
        }
        count++;
        logger.info("{}进行用户注册,最近{}秒钟时间内访问次数为{}", sourceIp, timeWindow, count);
        map.put(sourceIp, count);
        if (count > maxVisits) {
            R r = R.error("访问频繁，请稍后再试");
            String data = null;
            data = new String(JSON.toJSONString(r).getBytes());

            HttpHeaders headers = new HttpHeaders();
            headers.putAll(exchange.getResponse().getHeaders());
            headers.set(HttpHeaders.CONTENT_TYPE, "application/json;charset=utf-8");
            headers.set(HttpHeaders.ACCEPT_CHARSET, "utf-8");
            ServerHttpResponse newResponse = new ServerHttpResponseDecorator(response) {
                @Override
                public HttpHeaders getHeaders() {
                    return headers;
                }
            };

            DataBuffer wrap = newResponse.bufferFactory().wrap(data.getBytes());
            return newResponse.writeWith(Mono.just(wrap));
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        timer = new Timer();
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                map = new ConcurrentHashMap<>();
            }
        };
        timer.schedule(timerTask, timeWindow * 1000, timeWindow * 1000);
    }
}
